package com.xcc.strategypattern;

import com.xcc.strategypattern.demo01.Duck;
import com.xcc.strategypattern.demo01.MallardDuck;
import com.xcc.strategypattern.demo01.RedHeadDuck;
import com.xcc.strategypattern.demo01.RubberDuck;
import com.xcc.strategypattern.demo03.FlyRocketPowered;
import com.xcc.strategypattern.demo03.ModelDuck;
import com.xcc.strategypattern.demo04.*;
import com.xcc.strategypattern.demo04.Character;

/**
 * @Author: xiechuang
 * @Date: 2022/5/19
 */
public class Demo {

    public static void main(String[] args) {

        /**
         * 鸭子抽象类：鸭子会嘎嘎叫(quack())、会游泳(swim())
         * 变化1：鸭子存在不同的外观
         * 变化2：鸭子添加飞翔(fly())的功能
         * 变化3：鸭子不仅有动物，还有玩具鸭
         * 基础-->使用继承-->策略模式(将变化的内容抽离出来进行封装)
         */

        // ====== 鸭子有外观 ======
        System.out.println(">>>>>> 开始 <<<<<<");
        Duck duck1 = new MallardDuck();
        duck1.display();
        Duck duck2 = new RedHeadDuck();
        duck2.display();
        System.out.println(">>>>>> 结束 <<<<<<\n");

        // ====== 鸭子添加飞翔的功能：使用继承进行扩展 ======
        /**
         * 问题出现了，橡胶鸭居然用了飞翔的功能，显然这是不合理的
         * 在父类中添加飞翔的功能忽略了不是所有"鸭子"都会飞，如果在子类重写方法，这样是能临时解决问题，如果再添加诱饵鸭(DecoyDuck)呢？
         * 诱饵鸭不会飞也不会叫，橡胶鸭会叫不会飞
         * 继承的优缺点：
         *      优点：
         *          代码共享，减少类的创建
         *          提高复用性
         *          子类形似父类却又区别于父类
         *          提高代码的可扩展性
         *      缺点：
         *          继承是侵入性的。只要继承，就必须拥有父类的所有属性和方法：比如飞翔方法
         *          降低了代码的灵活性：橡胶鸭拥有了飞翔的功能(fly())
         *          增强了耦合性：父类中常量、变量和方法修改时，需要考虑子类的修改：如外观方法(display())
         */
        System.out.println(">>>>>> 开始 <<<<<<");
        Duck duck3 = new RubberDuck();
        duck3.display();
        duck3.fly();
        System.out.println(">>>>>> 结束 <<<<<<\n");

        // ====== 弃用继承，使用接口试试 ======
        /**
         * 使用接口虽然能解决问题，但是代码没法复用，并且如果飞行的动作如果有多种方式，需要在每个子类添加接口中的方法
         */
        System.out.println(">>>>>> 开始 <<<<<<");
        com.xcc.strategypattern.demo02.Duck duck4 = new com.xcc.strategypattern.demo02.RubberDuck();
        duck4.display();
        System.out.println(">>>>>> 结束 <<<<<<\n");

        // ====== 不变的是变化：将变化的代码抽取出来封装 ======
        System.out.println("设计原则：找出应用中可能需要变化之处，把他们独立出来，不要和那些不需要变化的代码混在一起");
        System.out.println(">>>>>> 开始 <<<<<<");
        com.xcc.strategypattern.demo03.Duck duck6 = new com.xcc.strategypattern.demo03.MallardDuck();
        duck6.performQuack();
        duck6.performFly();
        System.out.println(">>>>>> 结束 <<<<<<\n");

        // ====== 动态设定行为 ======
        System.out.println(">>>>>> 开始 <<<<<<");
        // 模型鸭初始化
        com.xcc.strategypattern.demo03.Duck duck7 = new ModelDuck();
        duck7.performFly();
        // 设定火箭飞行行为
        duck7.setFlyBehavior(new FlyRocketPowered());
        duck7.performFly();
        System.out.println(">>>>>> 结束 <<<<<<\n");


        // ====== 动作冒险游戏 ======
        System.out.println(">>>>>> 开始 <<<<<<");
        // 国王初始化：弓箭
        Character king = new King();
        System.out.print("国王：");
        king.fight();
        // 王后初始化：匕首
        Character queen = new Queen();
        System.out.print("王后：");
        queen.fight();
        // 骑士初始化：宝剑
        Character knight = new Knight();
        System.out.print("骑士：");
        knight.fight();
        // 恶魔初始化：斧头
        Character troll = new Troll();
        System.out.print("恶魔：");
        troll.fight();

        System.out.println("交换武器...");
        king.setWeaponBehavior(new KnifeBehavior());
        System.out.print("国王拿到匕首：");
        king.fight();

        queen.setWeaponBehavior(new SwordBehavior());
        System.out.print("王后拿到宝剑：");
        queen.fight();

        knight.setWeaponBehavior(new AxeBehavior());
        System.out.print("骑士拿到斧子：");
        knight.fight();

        troll.setWeaponBehavior(new BowAndArrowBehavior());
        System.out.print("恶魔拿到弓箭：");
        troll.fight();
        System.out.println(">>>>>> 结束 <<<<<<\n");

    }

}
